// 监控管理器

import { BaseManager } from '../core/BaseManager';
import { RedisClient } from '../core/RedisClient';
import { KeyGenerator } from '../utils/keyGenerator';

export interface PerformanceMetrics {
  timestamp: Date;
  responseTime: number;
  throughput: number;
  errorRate: number;
  memoryUsage: number;
  connectionCount: number;
  commandsProcessed: number;
}

export interface HealthCheckResult {
  status: 'healthy' | 'degraded' | 'unhealthy';
  timestamp: Date;
  checks: {
    connectivity: boolean;
    memory: boolean;
    latency: boolean;
    throughput: boolean;
  };
  metrics: {
    latency: number;
    memoryUsage: number;
    connectionCount: number;
    uptime: number;
  };
  issues: string[];
}

export interface AlertRule {
  name: string;
  metric: string;
  operator: 'gt' | 'lt' | 'eq' | 'gte' | 'lte';
  threshold: number;
  duration: number; // 持续时间（秒）
  enabled: boolean;
  severity: 'low' | 'medium' | 'high' | 'critical';
}

export interface Alert {
  id: string;
  rule: AlertRule;
  triggeredAt: Date;
  resolvedAt?: Date;
  status: 'active' | 'resolved';
  value: number;
  message: string;
}

export interface MonitoringStats {
  totalMetrics: number;
  activeAlerts: number;
  totalAlerts: number;
  healthCheckCount: number;
  lastHealthCheck: Date | null;
  uptime: number;
}

export class MonitoringManager extends BaseManager {
  private metrics: PerformanceMetrics[] = [];
  private alerts: Map<string, Alert> = new Map();
  private alertRules: Map<string, AlertRule> = new Map();
  private startTime: Date = new Date();
  private healthCheckInterval?: NodeJS.Timeout | undefined;
  private metricsCollectionInterval?: NodeJS.Timeout | undefined;

  constructor(client: RedisClient) {
    super(client, new KeyGenerator({ prefix: 'monitoring' }));
    this.initializeDefaultRules();
  }

  /**
   * 开始监控
   */
  async startMonitoring(
    options: {
      metricsInterval?: number;
      healthCheckInterval?: number;
      retentionPeriod?: number;
    } = {}
  ): Promise<void> {
    const {
      metricsInterval = 60000, // 1分钟
      healthCheckInterval = 30000, // 30秒
      retentionPeriod = 86400000, // 24小时
    } = options;

    // 开始收集性能指标
    this.metricsCollectionInterval = setInterval(async () => {
      try {
        await this.collectMetrics();
        await this.cleanupOldMetrics(retentionPeriod);
      } catch (error) {
        this.logger.error('Failed to collect metrics:', error);
      }
    }, metricsInterval);

    // 开始健康检查
    this.healthCheckInterval = setInterval(async () => {
      try {
        await this.performHealthCheck();
      } catch (error) {
        this.logger.error('Failed to perform health check:', error);
      }
    }, healthCheckInterval);

    this.logger.info('Monitoring started');
  }

  /**
   * 停止监控
   */
  stopMonitoring(): void {
    if (this.metricsCollectionInterval) {
      clearInterval(this.metricsCollectionInterval);
      this.metricsCollectionInterval = undefined;
    }

    if (this.healthCheckInterval) {
      clearInterval(this.healthCheckInterval);
      this.healthCheckInterval = undefined;
    }

    this.logger.info('Monitoring stopped');
  }

  /**
   * 收集性能指标
   */
  async collectMetrics(): Promise<PerformanceMetrics> {
    const startTime = this.now();

    try {
      // 测试延迟
      const latencyStart = Date.now();
      await this.execute('ping');
      const latency = Date.now() - latencyStart;

      // 获取Redis信息
      const info = await this.execute<string>('info');
      const infoLines = info.split('\r\n');

      let memoryUsage = 0;
      let connectionCount = 0;
      let commandsProcessed = 0;

      for (const line of infoLines) {
        if (line.startsWith('used_memory:')) {
          const value = line.split(':')[1];
          if (value) memoryUsage = parseInt(value, 10);
        } else if (line.startsWith('connected_clients:')) {
          const value = line.split(':')[1];
          if (value) connectionCount = parseInt(value, 10);
        } else if (line.startsWith('total_commands_processed:')) {
          const value = line.split(':')[1];
          if (value) commandsProcessed = parseInt(value, 10);
        }
      }

      const metrics: PerformanceMetrics = {
        timestamp: new Date(),
        responseTime: latency,
        throughput: this.calculateThroughput(),
        errorRate: this.calculateErrorRate(),
        memoryUsage,
        connectionCount,
        commandsProcessed,
      };

      this.metrics.push(metrics);

      // 检查告警规则
      await this.checkAlertRules(metrics);

      this.logMetric('monitoring.collect', this.now() - startTime, true, {
        latency,
        memoryUsage,
        connectionCount,
      });

      return metrics;
    } catch (error) {
      this.logMetric('monitoring.collect', this.now() - startTime, false, {
        error: (error as Error).message,
      });
      throw this.formatError(error, 'Failed to collect metrics');
    }
  }

  /**
   * 执行健康检查
   */
  async performHealthCheck(): Promise<HealthCheckResult> {
    const issues: string[] = [];

    // 连接性检查
    let connectivity = false;
    try {
      await this.execute('ping');
      connectivity = true;
    } catch (error) {
      issues.push('Redis connectivity failed');
    }

    // 延迟检查
    let latency = 0;
    let latencyOk = false;
    try {
      const latencyStart = Date.now();
      await this.execute('ping');
      latency = Date.now() - latencyStart;
      latencyOk = latency < 100; // 100ms阈值

      if (!latencyOk) {
        issues.push(`High latency: ${latency}ms`);
      }
    } catch (error) {
      issues.push('Latency check failed');
    }

    // 内存检查
    let memoryUsage = 0;
    let memoryOk = false;
    try {
      const info = await this.execute<string>('info', 'memory');
      const maxMemoryMatch = info.match(/maxmemory:(\d+)/);
      const usedMemoryMatch = info.match(/used_memory:(\d+)/);

      if (maxMemoryMatch && usedMemoryMatch && maxMemoryMatch[1] && usedMemoryMatch[1]) {
        const maxMemory = parseInt(maxMemoryMatch[1], 10);
        const usedMemory = parseInt(usedMemoryMatch[1], 10);
        memoryUsage = maxMemory > 0 ? (usedMemory / maxMemory) * 100 : 0;
        memoryOk = memoryUsage < 90; // 90%阈值

        if (!memoryOk) {
          issues.push(`High memory usage: ${memoryUsage.toFixed(1)}%`);
        }
      } else {
        memoryOk = true; // 如果无法获取内存信息，假设正常
      }
    } catch (error) {
      issues.push('Memory check failed');
    }

    // 吞吐量检查
    const throughput = this.calculateThroughput();
    const throughputOk = throughput > 0; // 简单检查

    // 连接数检查
    let connectionCount = 0;
    try {
      const info = await this.execute<string>('info', 'clients');
      const match = info.match(/connected_clients:(\d+)/);
      if (match?.[1]) {
        connectionCount = parseInt(match[1], 10);
      }
    } catch (error) {
      // 忽略连接数获取失败
    }

    // 确定整体状态
    let status: 'healthy' | 'degraded' | 'unhealthy';
    if (!connectivity) {
      status = 'unhealthy';
    } else if (issues.length > 2) {
      status = 'unhealthy';
    } else if (issues.length > 0) {
      status = 'degraded';
    } else {
      status = 'healthy';
    }

    const result: HealthCheckResult = {
      status,
      timestamp: new Date(),
      checks: {
        connectivity,
        memory: memoryOk,
        latency: latencyOk,
        throughput: throughputOk,
      },
      metrics: {
        latency,
        memoryUsage,
        connectionCount,
        uptime: Date.now() - this.startTime.getTime(),
      },
      issues,
    };

    this.logger.info(`Health check completed: ${status}`, {
      latency,
      memoryUsage,
      issues: issues.length,
    });

    return result;
  }

  /**
   * 添加告警规则
   */
  addAlertRule(rule: AlertRule): void {
    this.alertRules.set(rule.name, rule);
    this.logger.info(`Alert rule added: ${rule.name}`);
  }

  /**
   * 移除告警规则
   */
  removeAlertRule(name: string): boolean {
    const removed = this.alertRules.delete(name);
    if (removed) {
      this.logger.info(`Alert rule removed: ${name}`);
    }
    return removed;
  }

  /**
   * 获取活跃告警
   */
  getActiveAlerts(): Alert[] {
    return Array.from(this.alerts.values()).filter(alert => alert.status === 'active');
  }

  /**
   * 获取所有告警
   */
  getAllAlerts(): Alert[] {
    return Array.from(this.alerts.values());
  }

  /**
   * 获取最近的性能指标
   */
  getRecentMetrics(count: number = 10): PerformanceMetrics[] {
    return this.metrics.slice(-count);
  }

  /**
   * 获取监控统计信息
   */
  getStats(): MonitoringStats {
    const activeAlerts = this.getActiveAlerts().length;
    const lastHealthCheck =
      this.metrics.length > 0 ? (this.metrics[this.metrics.length - 1]?.timestamp ?? null) : null;

    return {
      totalMetrics: this.metrics.length,
      activeAlerts,
      totalAlerts: this.alerts.size,
      healthCheckCount: this.metrics.length,
      lastHealthCheck,
      uptime: Date.now() - this.startTime.getTime(),
    };
  }

  /**
   * 初始化默认告警规则
   */
  private initializeDefaultRules(): void {
    const defaultRules: AlertRule[] = [
      {
        name: 'high_latency',
        metric: 'responseTime',
        operator: 'gt',
        threshold: 100,
        duration: 60,
        enabled: true,
        severity: 'medium',
      },
      {
        name: 'high_memory_usage',
        metric: 'memoryUsage',
        operator: 'gt',
        threshold: 1024 * 1024 * 1024, // 1GB
        duration: 300,
        enabled: true,
        severity: 'high',
      },
      {
        name: 'high_error_rate',
        metric: 'errorRate',
        operator: 'gt',
        threshold: 0.05, // 5%
        duration: 120,
        enabled: true,
        severity: 'high',
      },
    ];

    for (const rule of defaultRules) {
      this.alertRules.set(rule.name, rule);
    }
  }

  /**
   * 检查告警规则
   */
  private async checkAlertRules(metrics: PerformanceMetrics): Promise<void> {
    for (const rule of this.alertRules.values()) {
      if (!rule.enabled) continue;

      const value = this.getMetricValue(metrics, rule.metric);
      const shouldAlert = this.evaluateRule(value, rule);

      if (shouldAlert) {
        await this.triggerAlert(rule, value);
      }
    }
  }

  /**
   * 获取指标值
   */
  private getMetricValue(metrics: PerformanceMetrics, metricName: string): number {
    switch (metricName) {
      case 'responseTime':
        return metrics.responseTime;
      case 'throughput':
        return metrics.throughput;
      case 'errorRate':
        return metrics.errorRate;
      case 'memoryUsage':
        return metrics.memoryUsage;
      case 'connectionCount':
        return metrics.connectionCount;
      default:
        return 0;
    }
  }

  /**
   * 评估告警规则
   */
  private evaluateRule(value: number, rule: AlertRule): boolean {
    switch (rule.operator) {
      case 'gt':
        return value > rule.threshold;
      case 'gte':
        return value >= rule.threshold;
      case 'lt':
        return value < rule.threshold;
      case 'lte':
        return value <= rule.threshold;
      case 'eq':
        return value === rule.threshold;
      default:
        return false;
    }
  }

  /**
   * 触发告警
   */
  private async triggerAlert(rule: AlertRule, value: number): Promise<void> {
    const alertId = `${rule.name}_${Date.now()}`;

    const alert: Alert = {
      id: alertId,
      rule,
      triggeredAt: new Date(),
      status: 'active',
      value,
      message: `${rule.name}: ${rule.metric} is ${value} (threshold: ${rule.threshold})`,
    };

    this.alerts.set(alertId, alert);

    this.logger.warn(`Alert triggered: ${alert.message}`, {
      rule: rule.name,
      value,
      threshold: rule.threshold,
      severity: rule.severity,
    });
  }

  /**
   * 计算吞吐量
   */
  private calculateThroughput(): number {
    // 简化实现：基于最近的指标计算
    if (this.metrics.length < 2) return 0;

    const recent = this.metrics.slice(-2);
    if (recent.length < 2 || !recent[0] || !recent[1]) return 0;

    const timeDiff = recent[1].timestamp.getTime() - recent[0].timestamp.getTime();
    const commandsDiff = recent[1].commandsProcessed - recent[0].commandsProcessed;

    return timeDiff > 0 ? (commandsDiff / timeDiff) * 1000 : 0; // 每秒命令数
  }

  /**
   * 计算错误率
   */
  private calculateErrorRate(): number {
    // 简化实现：返回固定的低错误率
    // 在实际项目中，应该跟踪失败的命令数
    return 0.001; // 0.1%
  }

  /**
   * 清理旧指标
   */
  private async cleanupOldMetrics(retentionPeriod: number): Promise<void> {
    const cutoffTime = Date.now() - retentionPeriod;
    this.metrics = this.metrics.filter(metric => metric.timestamp.getTime() > cutoffTime);
  }
}
